#!/usr/bin/env python
#-*- coding: utf-8 -*-

import re
import subprocess
import os
import sys
from collections import defaultdict

#==============================================

def strip_list(l):
	nl = list()
	for li in l:
		if len(li.strip())!=0:
			nl.append(li)
	return nl

def flatten_list(L):
	nl = list()
	for li in L:
		if len(li)!=0:
			if type(li)==type(""):
				nl.append(li)
			else:
				nl.extend(flatten_list(list(li)))
	return nl

#==============================================

def get_references(fname):
	
	_, ext = os.path.splitext(fname)
	fname = os.path.abspath(fname)
	
	if ext=='.doc':
		if os.name=='posix':
			try:
				txt = subprocess.Popen(['catdoc', '-wx', fname], stdout=subprocess.PIPE).stdout.read().replace("\xe2\x80\x93 ", "")
			except:
				return False, "Couldn't call catdoc...", None
			
		elif os.name=='nt':
			import pythoncom, win32com.client
			
			try:
				pythoncom.CoInitializeEx(pythoncom.COINIT_APARTMENTTHREADED)
				wordapp = win32com.client.DispatchEx("Word.Application")
				doc = wordapp.Documents.Open(fname)
				txt = doc.Content.Text
				wordapp.ActiveDocument.Close(win32com.client.constants.wdDoNotSaveChanges)
				wordapp.Quit()
				pythoncom.CoUninitialize()
			except Exception, e:
				print e
				return False, "Couldn't open Word...", None
			
			txt = txt.encode('utf-8').replace('\r\n', '\n').replace('\r', '\n')
			
	elif ext=='.txt':
		txt = open(fname, 'rb').read()
	
	lowercase = 'éèçàôêîù';
	uppercase = 'ÉÈÇÀÔÊÎÙ';
	
	author  = '((?:[vV]an |[vV]on |[dD]e |[dD]e la |[dD]el )?(?:Mc)?[A-Z%s][a-z%s-]+)' % (uppercase, lowercase)
	authorI = '((?:[vV]an |[vV]on |[dD]e |[dD]e la |[dD]el )?)((?:Mc)?[A-Z%s][a-z%s-]+)' % (uppercase, lowercase)
	date    = '([1-2][0-9]{3}[a-z]?)'
	
	authorBlock = '%s(?:,? (et al\.)?|(?:, %s)*,? (?:&|and) %s)?' % (author,author,author)
	dateBlock   = '%s(?:, %s)*' % (date, date)
	dateBlock   = '(?:(?:%s)|(?:\\(%s\\)))' % (dateBlock, dateBlock)
	
	citation = '('+authorBlock+',? '+dateBlock+')'
	
	reCite = re.compile(citation, re.UNICODE)
	reAuthors = re.compile(authorBlock)
	reDate = re.compile(dateBlock)
	reAuthor  = re.compile(authorI)
	
	references = dict();
	original_references = defaultdict(list)
	
	for f in reCite.findall(txt):
		c = f[0]
		a = flatten_list( reAuthors.findall(c) )
		d = flatten_list( reDate.findall(c)[0] )
		
		k = ''
		authors = ''
		for auth in a:
			if auth!="et al.":
				for a_part, a_name in reAuthor.findall(auth):
					#~ a_part = a_part.strip()
					k += a_name
					if authors=='':
						authors += auth
					else:
						authors += ", "+auth
			else:
				k += "~etal"
				authors += " et al."
		
		for dat in d:
			references[k+dat] = authors+" ("+dat+")"
			original_references[references[k+dat]].append(c)
		
	for k in original_references.keys():
		original_references[k] = set(original_references[k])
	
	sk = references.keys()
	sk.sort()
	
	references = [references[k] for k in sk]
	
	return True, references, {'original_references': dict(original_references), 'txt': txt}

#==============================================

if __name__=="__main__":
	#~ fname = "PGW_SHAR_2009-07-24_11h09.doc"
	#~ fname = "PGW_SHAR_2009.txt"
	fname = "test1.doc"
	#~ fname = sys.argv[1]
	
	ok, references, other = get_references(fname)
	
	t = ("\n".join(references)).decode('utf-8')
	print t.encode('utf-8')
	
	print "-"*50
	print len(references), "references"
	



